package com.imooc.activitiweb.controller;

import com.alibaba.fastjson.JSONObject;
import com.imooc.activitiweb.SecurityUtil;
import com.imooc.activitiweb.mapper.ActivitiMapper;
import com.imooc.activitiweb.mapper.UtilMapper;
import com.imooc.activitiweb.mapper.bus.BusHolidayMapper;
import com.imooc.activitiweb.pojo.UserInfoBean;
import com.imooc.activitiweb.pojo.bus.BusHolidayVO;
import com.imooc.activitiweb.util.AjaxResponse;
import com.imooc.activitiweb.util.GlobalConfig;
import io.swagger.annotations.ApiParam;
import org.activiti.api.model.shared.model.VariableInstance;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.*;

@RestController
@RequestMapping("/processInstance")
public class ProcessInstanceController {

    @Autowired
    private ProcessRuntime processRuntime;

    @Autowired
    private SecurityUtil securityUtil;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private UtilMapper utilMapper;

    @Autowired
    private ActivitiMapper activitiMapper;

    @Autowired
    private BusHolidayMapper busHolidayMapper;



    @GetMapping(value = "/getInstances")
    public AjaxResponse getInstances(@AuthenticationPrincipal UserInfoBean userInfoBean,
                                     @ApiParam(value = "页码")@RequestParam(value = "pageNum",defaultValue = "1")Integer pageNum,
                                     @ApiParam(value = "大小")@RequestParam(value = "pageSize",defaultValue = "10")Integer pageSize) {

        Page<ProcessInstance> processInstances = null;
        try {
            //PageHelper.startPage(pageNum,pageSize);
            //测试用写死的用户POSTMAN测试用；生产场景已经登录，在processDefinitions中可以获取到当前登录用户的信息
//            if (!GlobalConfig.Test) {
//                securityUtil.logInAs("wukong");
//            }
            //else {
            //  securityUtil.logInAs(userInfoBean.getUsername());//这句不需要
            // }

            processInstances=processRuntime.processInstances(Pageable.of((pageNum-1)*pageSize,pageSize));

            // processInstances=processRuntime.processInstances(Pageable.of(0,  50));
            //System.out.println("流程实例数量： " + processInstances.getTotalItems());
            List<ProcessInstance> list = processInstances.getContent();

            //先对其按照创建时间进行排序 （降序）
            list.sort((x,y)->y.getStartDate().compareTo(x.getStartDate()));

            List<HashMap<String, Object>> listMap = new LinkedList<HashMap<String, Object>>();
            for(ProcessInstance pi:list){
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("id", pi.getId());
                hashMap.put("name", pi.getName());
                hashMap.put("status", pi.getStatus());
                hashMap.put("processDefinitionId", pi.getProcessDefinitionId());
                hashMap.put("processDefinitionKey", pi.getProcessDefinitionKey());
                hashMap.put("startDate", pi.getStartDate());
                hashMap.put("processDefinitionVersion", pi.getProcessDefinitionVersion());
                //因为processRuntime.processDefinition("流程部署ID")查询的结果没有部署流程与部署ID，所以用repositoryService查询
                ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                        .processDefinitionId(pi.getProcessDefinitionId())
                        .singleResult();
                hashMap.put("resourceName", pd.getResourceName());
                hashMap.put("deploymentId", pd.getDeploymentId());
                listMap.add(hashMap);
            }
            //查到所有流程实例的总数
            int totalNum = runtimeService.createProcessInstanceQuery().list().size();
            //将总数 pageNum pageSize返回给前端
            JSONObject jsonData=new JSONObject();
            jsonData.put("totalNum",totalNum);
            jsonData.put("pageNum",pageNum);
            jsonData.put("pageSize",pageSize);
            jsonData.put("list",listMap);

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(),jsonData);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取流程实例失败", e.toString());
        }


    }


//    //启动
//    @GetMapping(value = "/startProcess1")
//    public AjaxResponse startProcess1(@RequestParam("processDefinitionId") String processDefinitionID,
//                                     @RequestParam(value = "instanceName",required = false) String instanceName,
//                                     @RequestParam(value = "instanceVariable",required = false) String instanceVariable
//    ) {
//        try {
//            if (!GlobalConfig.Test) {
//                securityUtil.logInAs("bajie");
//            }else{
//                securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
//            }
//
//            //启动流程实例
//            org.activiti.engine.runtime.ProcessInstance processInstance = null;
//            //processInstance = runtimeService.startProcessInstanceById(processDefinitionID);
//            Map<String,Object> variables=new HashMap<>();
//            variables.put("applicant",SecurityContextHolder.getContext().getAuthentication().getName());
//            processInstance=runtimeService.startProcessInstanceById(processDefinitionID,variables);
//
//            String instanceID = processInstance.getProcessInstanceId();//获取流程实例ID
//
//            //由于M6版本processInstance的bug（在启动创建实例的时候 无法带流程实例名称。因此在这里手写sql将流程实例名称插入到数据库中）
//            utilMapper.updateInstanceName(instanceName,instanceID);//在act_ru_execution表中写入流程实例名称
//
//            //通过流程实例ID查询此流程实例的当前任务ID————>instTaskID
//            String instTaskID =utilMapper.selectTaskInstanceIDByInstanceID(instanceID);
//
//            //启动流程实例后将流程实例ID等信息插入到请假流程表中
//            BusHolidayVO busHolidayVO=new BusHolidayVO();
//            busHolidayVO.setProcInstId(instanceID);
//
//            busHolidayVO.setProcDefId(processDefinitionID);
//            busHolidayVO.setUpdateTime(LocalDateTime.now());
//            busHolidayVO.setInstanceName(instanceName);
//            busHolidayVO.setCreateTime(new Date());
//            busHolidayVO.setCreator(SecurityContextHolder.getContext().getAuthentication().getName());
//            busHolidayMapper.insertSelective(busHolidayVO);
//
//            //把business_key和instTaskID返回给前端
//            JSONObject obj=new JSONObject();
//            obj.put("instTaskID",instTaskID);
//
//            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
//                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), obj);
//        } catch (Exception e) {
//            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
//                    "启动流程实例失败：" + e.toString(),null);
//        }
//    }

    //启动
    @GetMapping(value = "/startProcess")
    public AjaxResponse startProcess(@RequestParam("processDefinitionId") String processDefinitionID,
                                     @RequestParam(value = "instanceName",required = false) String instanceName,
                                     @RequestParam(value = "instanceVariable",required = false) String instanceVariable
    ) {
        try {
            if (!GlobalConfig.Test) {
                securityUtil.logInAs("bajie");
            }else{
                securityUtil.logInAs(SecurityContextHolder.getContext().getAuthentication().getName());
            }
            //必须用6的写法，因为7_m6版本查询报错，返回Query return 713 results instead of max 1
            org.activiti.engine.runtime.ProcessInstance processInstance = null;
            Map<String,Object> variables=new HashMap<>();
            variables.put("applicant",SecurityContextHolder.getContext().getAuthentication().getName());
            //启动流程实例
            processInstance=runtimeService.startProcessInstanceById(processDefinitionID,variables);
            //由于M6版本processInstance的bug（在启动创建实例的时候 无法带流程实例名称。因此在这里手写sql将流程实例名称插入到数据库中）
            utilMapper.updateInstanceName(instanceName,processInstance.getProcessInstanceId());//在act_ru_execution表中写入流程实例名称
            String taskInstanceID =utilMapper.selectTaskInstanceIDByInstanceID(processInstance.getProcessInstanceId());

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), taskInstanceID);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "启动流程实例失败：" + e.toString(),null);
        }
    }

    //删除
    @GetMapping(value = "/deleteInstance")
    public AjaxResponse deleteInstance(@RequestParam("instanceID") String instanceID) {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("wukong");
            }
            //删除流程后 应当删除各种流程表的相关数据
            activitiMapper.deleteHolidayProcessData(instanceID);
            activitiMapper.deleteHolidayHistoryData(instanceID);
            ProcessInstance processInstance = processRuntime.delete(ProcessPayloadBuilder
                    .delete()
                    .withProcessInstanceId(instanceID)
                    .build()
            );
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
        }
     catch(Exception e)
        {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "删除流程实例失败", e.toString());
        }

    }

    //挂起冷冻
    @GetMapping(value = "/suspendInstance")
    public AjaxResponse suspendInstance(@RequestParam("instanceID") String instanceID) {

        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("wukong");
            }

            ProcessInstance processInstance = processRuntime.suspend(ProcessPayloadBuilder
                    .suspend()
                    .withProcessInstanceId(instanceID)
                    .build()
            );
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
        }
        catch(Exception e)
        {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "挂起流程实例失败", e.toString());
        }
    }

    //激活
    @GetMapping(value = "/resumeInstance")
    public AjaxResponse resumeInstance(@RequestParam("instanceID") String instanceID) {

        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("wukong");
            }

            ProcessInstance processInstance = processRuntime.resume(ProcessPayloadBuilder
                    .resume()
                    .withProcessInstanceId(instanceID)
                    .build()
            );
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), processInstance.getName());
        }
        catch(Exception e)
        {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "激活流程实例失败", e.toString());
        }
    }


    //获取参数
    @GetMapping(value = "/variables")
    public AjaxResponse variables(@RequestParam("instanceID") String instanceID) {
        try {
            if (GlobalConfig.Test) {
                securityUtil.logInAs("wukong");
            }
            List<VariableInstance> variableInstance = processRuntime.variables(ProcessPayloadBuilder
                    .variables()
                    .withProcessInstanceId(instanceID)
                    .build());

            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), variableInstance);
        }
        catch(Exception e)
        {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "获取流程参数失败", e.toString());
        }
    }





    
}
